﻿#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/select.h>
#include <time.h>
#include <stdint.h> // 添加uint32_t支持
#include "logo.h"
//gcc Transmis_handshake.c logo.c -o transmis_handshake 
// 定义串口设备路径和波特率宏
#define SERIAL_PORT "/dev/ttyCH9344USB2"
#define BAUDRATE    B115200
#define TIMEOUT_SEC 20           // 等待超时时间（秒）
#define CHUNK_SIZE  128          // 数据块大小

// 协议相关定义
#define START_CMD   "Transmit_logo"
#define OK_RESPONSE "Transmit_logo_OK"
#define CONTINUE_CMD "continue"
#define END_CMD     "Transmit_logo_end"

// 尺寸信息包标记（改为16位）
#define SIZE_MARKER1 150 //宽
#define SIZE_MARKER2 150 //高

// 起始地址定义
#define START_ADDRESS 0x0 // 尺寸等起始地址必须是64K，0x100的倍数，0除外

// 状态枚举
typedef enum {
    STATE_SEND_START,
    STATE_WAIT_OK,
    STATE_SEND_SIZE_INFO,       // 发送尺寸信息（提前发送）
    STATE_WAIT_SIZE_CONTINUE,   // 等待尺寸信息确认
    STATE_SEND_DATA,
    STATE_WAIT_CONTINUE,
    STATE_WAIT_FINAL_CONTINUE,
    STATE_SEND_END,             
    STATE_EXIT
} TransferState;

// 从串口读取一行数据（带超时）
int read_line(int fd, char *buffer, size_t buf_size, int timeout_sec) {
    size_t index = 0;
    time_t start_time = time(NULL);
    
    while (index < buf_size - 1) {
        // 检查超时
        if (time(NULL) - start_time > timeout_sec) {
            return -1; // 超时
        }
        
        // 使用select检查数据可用性
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        
        struct timeval tv = {
            .tv_sec = 1,
            .tv_usec = 0
        };
        
        int rv = select(fd + 1, &fds, NULL, NULL, &tv);
        if (rv > 0) {
            char c;
            ssize_t n = read(fd, &c, 1);
            if (n == 1) {
                // 打印接收到的字符
                putchar(c);
                fflush(stdout);
                
                // 存储字符（过滤回车符）
                if (c != '\r') {
                    buffer[index++] = c;
                }
                
                // 检测到换行符表示一行结束
                if (c == '\n') {
                    buffer[index] = '\0'; // 终止字符串
                    return index; // 成功读取一行
                }
            } else if (n < 0) {
                perror("Read error");
                return -2; // 读取错误
            }
        } else if (rv < 0) {
            perror("Select error");
            return -2; // select错误
        }
    }
    
    return -3; // 缓冲区溢出
}

int main() {
    int fd;
    ssize_t bytes_written;
    size_t total_bytes = gImage_logo_size;
    size_t sent = 0;
    TransferState state = STATE_SEND_START;
    
    printf("Total bytes to send: %zu (0x%08zX)\n", total_bytes, total_bytes);
    
    // 打开串口设备
    fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        perror("Error opening serial port");
        return 1;
    }
    
    // 配置串口参数
    struct termios options;
    tcgetattr(fd, &options);
    cfsetispeed(&options, BAUDRATE);
    cfsetospeed(&options, BAUDRATE);
    
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CRTSCTS;
    options.c_cflag |= (CLOCAL | CREAD);
    
    options.c_lflag = 0;
    options.c_oflag = 0;
    options.c_cc[VTIME] = 0; // 非规范模式不使用超时
    options.c_cc[VMIN] = 0;
    
    tcsetattr(fd, TCSANOW, &options);
    tcflush(fd, TCIOFLUSH);
    
    // 状态机主循环
    while (state != STATE_EXIT) {
        switch (state) {
            case STATE_SEND_START: {
                // 发送开始命令
                printf("\nSending start command: %s\n", START_CMD);
                bytes_written = write(fd, START_CMD, strlen(START_CMD));
                if (bytes_written < 0) {
                    perror("Write error");
                    state = STATE_EXIT;
                } else {
                    // 添加换行符确保命令被识别
                    write(fd, "\n", 1);
                    state = STATE_WAIT_OK;
                }
                break;
            }
                
            case STATE_WAIT_OK: {
                // 等待OK响应
                printf("Waiting for OK response...\n");
                char response[64];
                int rv = read_line(fd, response, sizeof(response), TIMEOUT_SEC);
                
                if (rv > 0) {
                    // 检查响应内容
                    if (strstr(response, OK_RESPONSE) != NULL) {
                        printf("\nReceived OK response. Sending size info first.\n");
                        state = STATE_SEND_SIZE_INFO; // 修改：提前发送尺寸信息
                    } else {
                        printf("\nUnexpected response: %s\n", response);
                        state = STATE_EXIT;
                    }
                } else {
                    printf("\nTimeout or error waiting for OK response\n");
                    state = STATE_EXIT;
                }
                break;
            }
                
            // 修改：提前发送尺寸信息（改为12字节）
            case STATE_SEND_SIZE_INFO: {
                // 准备12字节尺寸信息包
                unsigned char size_info[12];
                uint32_t size_value = (uint32_t)total_bytes; // 转换为32位整数
                
                // 按照要求分解32位大小值（大端序）
                // 大小值（4字节）
                size_info[0] = (size_value >> 24) & 0xFF; // 最高位字节
                size_info[1] = (size_value >> 16) & 0xFF;
                size_info[2] = (size_value >> 8) & 0xFF;
                size_info[3] = size_value & 0xFF;         // 最低位字节
                
                // 标记1（SIZE_MARKER1 = 0xAABB，拆分为2字节）
                size_info[4] = (SIZE_MARKER1 >> 8) & 0xFF; // 0xAA
                size_info[5] = SIZE_MARKER1 & 0xFF;        // 0xBB
                
                // 标记2（SIZE_MARKER2 = 0xCCDD，拆分为2字节）
                size_info[6] = (SIZE_MARKER2 >> 8) & 0xFF; // 0xCC
                size_info[7] = SIZE_MARKER2 & 0xFF;        // 0xDD
                
                // 起始地址（START_ADDRESS = 0x12345678，拆分为4字节）
                size_info[8] = (START_ADDRESS >> 24) & 0xFF; // 0x0
                size_info[9] = (START_ADDRESS >> 16) & 0xFF; // 0x0
                size_info[10] = (START_ADDRESS >> 8) & 0xFF; // 0x0
                size_info[11] = START_ADDRESS & 0xFF;        // 0x0
                
                // 打印完整的12字节信息
                printf("\nSending size info: [");
                for (int i = 0; i < 12; i++) {
                    printf("0x%02X", size_info[i]);
                    if (i < 11) printf(", ");
                }
                printf("]\n");
                
                // 发送尺寸信息
                bytes_written = write(fd, size_info, sizeof(size_info));
                if (bytes_written != sizeof(size_info)) {
                    perror("Error sending size info");
                    state = STATE_EXIT;
                } else {
                    state = STATE_WAIT_SIZE_CONTINUE;
                }
                break;
            }
                
            // 修改：等待尺寸信息确认
            case STATE_WAIT_SIZE_CONTINUE: {
                // 等待尺寸信息确认
                printf("\nWaiting for size info continue command...\n");
                char command[32];
                int rv = read_line(fd, command, sizeof(command), TIMEOUT_SEC);
                
                if (rv > 0) {
                    if (strstr(command, CONTINUE_CMD) != NULL) {
                        state = STATE_SEND_DATA; // 尺寸确认后开始发送图像数据
                    } else {
                        printf("\nUnexpected command after size info: %s\n", command);
                        state = STATE_EXIT;
                    }
                } else {
                    printf("\nTimeout waiting for size info continue\n");
                    state = STATE_EXIT;
                }
                break;
            }
                
            case STATE_SEND_DATA: {
                // 发送数据块
                size_t to_send = (total_bytes - sent > CHUNK_SIZE) ? 
                                CHUNK_SIZE : total_bytes - sent;
                
                bytes_written = write(fd, &gImage_logo[sent], to_send);
                if (bytes_written < 0) {
                    perror("Write error");
                    state = STATE_EXIT;
                    break;
                }
                
                sent += bytes_written;
                printf("\nSent %zd/%zu bytes (%.1f%%)", 
                       sent, total_bytes, (sent * 100.0) / total_bytes);
                
                // 检查是否完成所有数据传输
                if (sent >= total_bytes) {
                    // 所有数据已发送，等待最后一次continue
                    state = STATE_WAIT_FINAL_CONTINUE;
                } else {
                    state = STATE_WAIT_CONTINUE;
                }
                break;
            }
                
            case STATE_WAIT_CONTINUE: {
                // 等待继续命令
                printf("\nWaiting for continue command...\n");
                char command[32];
                int rv = read_line(fd, command, sizeof(command), TIMEOUT_SEC);
                
                if (rv > 0) {
                    if (strstr(command, CONTINUE_CMD) != NULL) {
                        state = STATE_SEND_DATA;
                    } else {
                        printf("\nUnexpected command: %s\n", command);
                        state = STATE_EXIT;
                    }
                } else {
                    printf("\nTimeout or error waiting for continue command\n");
                    state = STATE_EXIT;
                }
                break;
            }
                
            case STATE_WAIT_FINAL_CONTINUE: {
                // 等待最后一次continue确认
                printf("\nWaiting for final continue command...\n");
                char command[32];
                int rv = read_line(fd, command, sizeof(command), TIMEOUT_SEC);
                
                if (rv > 0) {
                    if (strstr(command, CONTINUE_CMD) != NULL) {
                        // 收到最后一次continue，准备发送结束命令
                        state = STATE_SEND_END;
                    } else {
                        printf("\nUnexpected command after final block: %s\n", command);
                        state = STATE_EXIT;
                    }
                } else {
                    printf("\nTimeout waiting for final continue\n");
                    state = STATE_EXIT;
                }
                break;
            }
                
            case STATE_SEND_END: {
                // 确保串口缓冲区清空
                tcdrain(fd);
                usleep(100); // 100ms 确保物理传输完成
                
                // 单独发送结束命令
                printf("\nSending end command: %s\n", END_CMD);
                bytes_written = write(fd, END_CMD, strlen(END_CMD));
                if (bytes_written < 0) {
                    perror("Write error in end command");
                } else {
                    // 添加换行符确保命令被识别
                    write(fd, "\n", 1);
                    // 确保结束命令完全发送
                    tcdrain(fd);
                }
                state = STATE_EXIT;
                break;
            }
                
            case STATE_EXIT:
                break;
        }
    }
    
    printf("\nTransfer %s. Total bytes sent: %zu\n", 
           (sent >= total_bytes) ? "completed" : "aborted", sent);
    
    close(fd);
    return (sent >= total_bytes) ? 0 : 1;
}